package com.tcxhb.job.dao.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcxhb.job.common.constants.enums.ExecuteStatus;
import com.tcxhb.job.common.constants.enums.ScheduleStatus;
import com.tcxhb.job.common.model.PageResponse;
import com.tcxhb.job.dao.dataobject.JobInstanceDO;
import com.tcxhb.job.dao.dataobject.query.JobInstanceQuery;
import com.tcxhb.job.dao.mapper.JobInstanceMapper;
import com.tcxhb.job.dao.repository.JobInstanceRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * author:auto.generator
 * time: 2023-11-05
 */
@Repository
public class JobInstanceRepositoryImpl extends ServiceImpl<JobInstanceMapper, JobInstanceDO> implements JobInstanceRepository {

    @Override
    public Long create(JobInstanceDO jobInstanceDO) {
        super.save(jobInstanceDO);
        return jobInstanceDO.getId();
    }

    @Override
    public boolean deleteById(Long id) {
        return super.removeById(id);
    }

    @Override
    public boolean updateById(JobInstanceDO instanceDO) {
        LambdaUpdateWrapper<JobInstanceDO> wrapper = Wrappers.<JobInstanceDO>lambdaUpdate();
        wrapper.eq(JobInstanceDO::getId, instanceDO.getId());
        wrapper.ne(JobInstanceDO::getExecuteStatus, ExecuteStatus.SUCC.getType());
        //
        if (instanceDO.getMachineAddr() != null) {
            wrapper.set(JobInstanceDO::getMachineAddr, instanceDO.getMachineAddr());
        }
        if (instanceDO.getRetryFlag() != null) {
            wrapper.set(JobInstanceDO::getRetryFlag, instanceDO.getRetryFlag());
        }
        //执行信息
        if (instanceDO.getExecuteStatus() != null) {
            wrapper.set(JobInstanceDO::getExecuteStatus, instanceDO.getExecuteStatus());
        }
        if (instanceDO.getMsg() != null) {
            wrapper.set(JobInstanceDO::getMsg, instanceDO.getMsg());
        }
        if (instanceDO.getExecuteTime() != null) {
            wrapper.set(JobInstanceDO::getExecuteTime, instanceDO.getExecuteTime());
        }
        //调度信息
        if (instanceDO.getScheduleStatus() != null) {
            wrapper.set(JobInstanceDO::getScheduleStatus, instanceDO.getScheduleStatus());
        }
        //失败次数
        if (instanceDO.getFailCount() != null) {
            wrapper.set(JobInstanceDO::getFailCount, instanceDO.getFailCount());
        }
        return super.update(instanceDO, wrapper);
    }

    @Override
    public JobInstanceDO queryById(Long id) {
        return super.getById(id);
    }

    @Override
    public PageResponse<JobInstanceDO> page(JobInstanceQuery query) {
        LambdaQueryWrapper<JobInstanceDO> wrapper = queryWrapper(query);
        wrapper.orderByDesc(JobInstanceDO::getId);
        Page<JobInstanceDO> page = new Page<>(query.getPage().getPageNum(), query.getPage().getPageSize());
        IPage response = page(page, wrapper);
        PageResponse result = new PageResponse();
        result.setTotal(response.getTotal());
        result.setList(response.getRecords());
        return result;
    }

    @Override
    public List<JobInstanceDO> list(JobInstanceQuery query) {
        LambdaQueryWrapper<JobInstanceDO> wrapper = queryWrapper(query);
        return super.list(wrapper);
    }

    @Override
    public JobInstanceDO queryByTraceId(Long jobId, String traceId) {
        LambdaQueryWrapper<JobInstanceDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(JobInstanceDO::getTraceId, traceId);
        wrapper.eq(JobInstanceDO::getJobId, jobId);
        return super.getOne(wrapper);
    }

    @Override
    public List<JobInstanceDO> scan(JobInstanceQuery query) {
        LambdaQueryWrapper<JobInstanceDO> wrapper = queryWrapper(query);
        if (query.getPage() != null) {
            wrapper.last(" limit " + query.getPage().getPageSize());
        }
        wrapper.select(
                JobInstanceDO::getId,
                JobInstanceDO::getExecuteStatus,
                JobInstanceDO::getScheduleStatus,
                JobInstanceDO::getMachineAddr
        );
        wrapper.orderByAsc(JobInstanceDO::getId);
        return super.list(wrapper);
    }

    private LambdaQueryWrapper<JobInstanceDO> queryWrapper(JobInstanceQuery query) {
        LambdaQueryWrapper<JobInstanceDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(query.getId() != null, JobInstanceDO::getId, query.getId());
        wrapper.eq(query.getJobId() != null, JobInstanceDO::getJobId, query.getJobId());
        //用来查询分片任务
        if (StringUtils.isNotBlank(query.getTraceId())) {
            wrapper.likeRight(JobInstanceDO::getTraceId, query.getTraceId());
        }
        if (StringUtils.isNotBlank(query.getAppName())) {
            wrapper.eq(JobInstanceDO::getAppName, query.getAppName());
        }
        //上一次ID
        if (query.getLastId() != null) {
            wrapper.gt(JobInstanceDO::getId, query.getLastId());
        }
        //最小状态
        if (query.getMinExeStatus() != null) {
            wrapper.ge(JobInstanceDO::getExecuteStatus, query.getMinExeStatus());
        }
        //最大状态
        if (query.getMaxExeStatus() != null) {
            wrapper.le(JobInstanceDO::getExecuteStatus, query.getMaxExeStatus());
        }
        // 重试条件机制
        if (query.getRetryFlag() != null && query.getRetryFlag() == 1) {
            wrapper.eq(JobInstanceDO::getRetryFlag, query.getRetryFlag());
            wrapper.and(w -> w
                    .eq(JobInstanceDO::getExecuteStatus, ExecuteStatus.FAIL.getType())
                    .or()
                    .eq(JobInstanceDO::getScheduleStatus, ScheduleStatus.FAIL.getType())
            );
        }
        //状态
        wrapper.eq(query.getScheduleStatus() != null, JobInstanceDO::getScheduleStatus, query.getScheduleStatus());
        wrapper.eq(query.getExecuteStatus() != null, JobInstanceDO::getExecuteStatus, query.getExecuteStatus());
        // 任务调度时间
        if (query.getScheduleTimeStart() != null) {
            wrapper.ge(JobInstanceDO::getScheduleTime, query.getScheduleTimeStart());
        }
        return wrapper;
    }
}
